package com.fractalist.base.core.web;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.nutz.json.Json;

import com.fractalist.base.core.constants.SystemConstants;
import com.fractalist.base.core.helper.ApplicationHelper;
import com.fractalist.base.core.utils.CookieUtils;
import com.fractalist.base.core.utils.StringUtil;
import com.fractalist.base.core.web.result.ChainResult;
import com.fractalist.base.core.web.result.DispatcherResult;
import com.fractalist.base.core.web.result.RedirectResult;
import com.fractalist.base.core.web.result.StringResult;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.inject.Inject;

/**
 * 所有action的基类，扩展了很多辅助action操作的方法
 * 
 * @author radio
 * 
 */
public class BaseActionSupport extends ActionSupport {

	private static final long serialVersionUID = 5208748057591198755L;

	protected ActionMapper actionMapper;

	protected String methodName;

	public static String basePath;

	public static String baseAllPath;

	public BaseActionSupport() {
		HttpServletRequest request = getRequest();
		if (null == basePath || basePath.length() <= 0) {
			basePath = request.getContextPath();
		}
		if (null == baseAllPath || baseAllPath.length() <= 0) {
			baseAllPath = request.getScheme() + "://" + request.getServerName() + ":"
					+ request.getServerPort() + basePath;
		}
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	@Inject
	public void setActionMapper(ActionMapper mapper) {
		this.actionMapper = mapper;
	}

	/**
	 * 获取servletContext
	 * 
	 * @return
	 */
	protected ServletContext getServletContext() {
		return ServletActionContext.getServletContext();
	}

	/**
	 * 获得request的method，是POST还是GET还是其他方法
	 * 
	 * @return
	 */
	protected String getMethod() {
		return getRequest().getMethod().toUpperCase();
	}

	/**
	 * 存储cookie的方法
	 * 
	 * @param key
	 * @param value
	 */
	public void addCookie(String key, String value) {
		if (!ApplicationHelper.isBlank(key) && !ApplicationHelper.isBlank(value)) {
			CookieUtils.setCookie(getRequest(), getResponse(), key, value.replace("@", ","),
					SystemConstants.COOKIE_MAX_AGE);
		}
	}

	/**
	 * 清楚用户的cookie信息
	 * 
	 * @param key
	 */
	public void clearCookie(String key) {
		if (!ApplicationHelper.isBlank(key)) {
			CookieUtils.setCookie(getRequest(), getResponse(), key, null, 0);
		}
	}

	/**
	 * 获取HttpServletRequest
	 * 
	 * @return
	 */
	protected HttpServletRequest getRequest() {
		return ServletActionContext.getRequest();
	}

	/**
	 * 获取HttpServletResponse
	 * 
	 * @return
	 */
	protected HttpServletResponse getResponse() {
		return ServletActionContext.getResponse();
	}

	/**
	 * 获得HttpSession，如果SESSION_CLUSTERID为true,
	 * 则使用HttpSessionWrapper来构建HttpSession获得session集群的特性
	 * 
	 * @see HttpSessionWrapper
	 */
	protected HttpSession getSession() {
		return getRequest().getSession();
	}

	/**
	 * 将数据存入ActionContext中，供页面显示
	 * 
	 * @param key
	 *            页面调用的值 ${key}
	 * @param value
	 *            与key对应的数据
	 */
	protected void putObjToContext(String key, Object value) {
		ActionContext.getContext().put(key, value);
	}

	/**
	 * 从ActionContext中取得对象数据
	 * 
	 * @param key
	 *            ActionContext中的key
	 * @return 与key对应的value
	 */
	protected Object getObjFromContext(String key) {
		return ActionContext.getContext().get(key);
	}

	/**
	 * 将action中的消息显示到页面，消息码保存在messageMap的message中
	 * 
	 * @param value
	 *            要显示的消息码
	 */
	@SuppressWarnings("unchecked")
	protected void displayMsg(String value) {
		if (!value.equals("")) {
			HashMap<String, String> map = (HashMap<String, String>) getObjFromContext("messageMap");
			if (map == null || map.keySet().size() == 0) {
				map = new HashMap<String, String>();
			}
			map.put("message", value);
			putObjToContext("messageMap", map);
		}
	}

	/**
	 * 将数据存入session中
	 * 
	 * @param key
	 *            页面调用的值 ${key}
	 * @param value
	 *            与key对应的数据
	 */
	protected void putObjToSession(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	/**
	 * 根据key从session中取出对象数据
	 * 
	 * @param key
	 *            session中的key
	 * @return 与key对应的数据
	 */
	protected Object getObjFromSession(String key) {
		HttpSession session = getSession();
		if (key == null || session == null) {
			return null;
		} else {
			return session.getAttribute(key);
		}
	}

	/**
	 * 从request中取得参数
	 * 
	 * @param key
	 *            页面传递的参数名
	 * @return 参数值，如果传递的为null返回空字符串
	 */
	protected String getParameterFromRequest(String key) {
		String parameter = getRequest().getParameter(key);
		if (parameter == null) {
			parameter = "";
		}
		return parameter;
	}

	/**
	 * 通过ftl模板，action中输出html代码到页面中
	 * 
	 * @param data
	 *            模板中所需要的数据
	 * @param fileName
	 *            模板的文件名
	 * 
	 * @see FreeMarkerEngine
	 * @see StringResult
	 */
	/*
	 * protected String renderHtml(Map<String, Object> data, String fileName) {
	 * if (fileName != null && !fileName.equalsIgnoreCase(""))
	 * putObjToContext("result", freeMarkerEngine.getHtml(data,
	 * getServletContext(), fileName)); return "renderString"; }
	 */

	/**
	 * action中输出字符串到页面中
	 * 
	 * @param text
	 *            要输出的字符串
	 * 
	 * @see StringResult
	 */
	protected String renderText(String text) {
		if (text != null && !text.equalsIgnoreCase("")) {
			putObjToContext("result", text);
		}
		return "renderString";
	}

	/**
	 * 将action中得到的数据以json格式进行输出，如果对象不存在则输出空字符串
	 * 
	 * @param obj
	 *            要转换成json的对象，只支持自定义类和集合类型
	 * 
	 * @see StringResult
	 */
	protected String renderJson(Object obj) {
		if (obj != null) {
			String json = Json.toJson(obj);
			putObjToContext("result", json);
		}
		return "renderString";
	}

	/**
	 * 执行action后跳转到指定的url中，跳转时不带传递任何参数<br>
	 * return redirect("/account/accountList.jsp")
	 * 
	 * @param url
	 *            指定的url路径
	 * @return jspRedirect类型的result
	 * 
	 * @see RedirectResult
	 */
	protected String redirect(String url) {
		String location = "/";
		if (url != null && !url.equalsIgnoreCase("")) {
			location = url;
		}
		putObjToContext("location", location);
		return "jspRedirect";
	}

	/**
	 * 执行action后渲染指定的jsp页面<br>
	 * return dispatcher("/account/accountList.jsp")
	 * 
	 * @param url
	 *            指定的url路径
	 * @return jspDiapatcher类型的result
	 * 
	 * @see DispatcherResult
	 */
	protected String dispatcher(String url) {
		String location = "/";
		if (url != null && !url.equalsIgnoreCase("")) {
			location = url;
		}
		putObjToContext("location", location);
		return "jspDiapatcher";
	}

	/**
	 * 将action链接到另一个指定地址的action中，形成action链。不必写action的后缀<br>
	 * return chain("/account/viewAccount")
	 * 
	 * @param url
	 *            action的路径地址
	 * @return actionChain类型的result
	 * 
	 * @see ChainResult
	 */
	protected String chain(String url) {
		String location = "/";
		if (url != null && !url.equalsIgnoreCase("")) {
			location = url;
		}
		putObjToContext("location", location);
		return "actionChain";
	}

	/**
	 * 验证model的所有属性
	 * 
	 * @param obj
	 *            被验证的model,必须继承自entityDao
	 * 
	 * @see EntityDao#validate()
	 * 
	 */
	/*
	 * @SuppressWarnings("unchecked") protected boolean
	 * pojoValidate(AbstractIdEntity obj) { if (obj == null) { return false; }
	 * return handleMsg(validateManager.validate(obj.getClass())); }
	 */

	/**
	 * 验证model的指定一个属性
	 * 
	 * @param obj
	 *            被验证的model,必须继承自entityDao
	 * @param filed
	 *            指定的属性名
	 * 
	 * @see EntityDao#validate()
	 * 
	 */
	/*
	 * @SuppressWarnings("unchecked") protected boolean
	 * pojoValidate(AbstractIdEntity obj, String filed) { if (obj == null) {
	 * return false; } return handleMsg(validateManager.validate(obj.getClass(),
	 * filed)); }
	 */

	/**
	 * 验证model后对错误信息的处理，将错误信息保存到messageMap中
	 * 
	 * @param map
	 *            验证后的错误信息
	 * 
	 */
	@SuppressWarnings("unchecked")
	private boolean handleMsg(Map<String, String> map) {
		ActionContext ctx = ActionContext.getContext();
		HashMap<String, String> msg = (HashMap<String, String>) ctx.get("messageMap");
		if (msg == null || msg.keySet().size() == 0) {
			msg = (HashMap<String, String>) map;
		} else {
			Iterator<String> it = map.keySet().iterator();
			while (it.hasNext()) {
				String key = it.next();
				msg.put(key, map.get(key));
			}
		}
		ctx.put("messageMap", msg);
		return map.keySet().size() > 0;
	}

	/**
	 * 根据map中的数据来拼接查询的链接<br>
	 * pageLinkToContext("/account/viewAccount.action",map)
	 * 
	 * @param actionName
	 *            action的名称
	 * @param map
	 *            链接中的数据和参数名
	 * 
	 * @see ApplicationHelper#buildSearchLink(Map)
	 */
	protected void pageLinkToContext(String actionName, Map<String, Object> map) {
		StringBuffer sb = new StringBuffer();
		sb.append(actionName).append("?");
		sb.append(ApplicationHelper.buildSearchLink(map));
		putObjToContext("pageLink", sb.toString());
	}

	/**
	 * 保存文件
	 * 
	 * @param file
	 * @param path
	 * @param fileName
	 * @return
	 */
	protected boolean saveFile(File file, String path, String fileName) {
		boolean retB = false;
		FileOutputStream fos = null;
		FileInputStream fis = null;
		try {
			// 建立文件输出流
			fos = new FileOutputStream(path + "/" + fileName);
			// 建立文件上传流
			fis = new FileInputStream(file);
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = fis.read(buffer)) > 0) {
				fos.write(buffer, 0, len);
			}
			retB = true;
		} catch (Exception e) {
			retB = false;
			System.out.println(">>>>>>>>>>>>>>>>文件上传失败<<<<<<<<<<<<<<<<<<<<<<");
			e.printStackTrace();
		} finally {
			close(fos, fis);
		}
		return retB;
	}

	/**
	 * 删除文件
	 * 
	 * @param fileUrl
	 *            数据库中文件存放的url
	 * @return
	 */
	public boolean deleteFile(String fileUrl) {
		boolean retB = false;

		try {

			if (!StringUtil.isnull(fileUrl) && !StringUtil.isnull(fileUrl)) {

				File file = new File(fileUrl);
				if (file.exists()) {
					retB = file.delete();
				}
			}

		} catch (Exception e) {
			retB = false;
			System.out.println(">>>>>>>>>>>>>>>>文件删除失败<<<<<<<<<<<<<<<<<<<<<<");
			e.printStackTrace();
		}
		return retB;
	}

	/**
	 * 关闭输入输出流
	 * 
	 * @param fos
	 * @param fis
	 */
	private void close(FileOutputStream fos, FileInputStream fis) {
		if (fis != null) {
			try {
				fis.close();
			} catch (IOException e) {
				System.out.println("FileInputStream关闭失败");
				e.printStackTrace();
			}
		}
		if (fos != null) {
			try {
				fos.close();
			} catch (IOException e) {
				System.out.println("FileOutputStream关闭失败");
				e.printStackTrace();
			}
		}
	}

	/**
	 * 获取文件名称
	 * 
	 * @param imageFileName
	 * @return
	 */
	protected String getFileName(String imageFileUrl) {
		if (!StringUtil.isnull(imageFileUrl)) {

			if (imageFileUrl.indexOf("/") > 0) {
				try {
					return imageFileUrl.substring(imageFileUrl.lastIndexOf(("/") + 1));
				} catch (Exception ex) {
					return "";
				}
			} else {
				return "";
			}
		} else {
			return "";
		}
	}

	/**
	 * 获取文件后缀
	 * 
	 * @param imageFileName
	 * @return
	 */
	protected String getFileSuffix(String imageFileName) {

		if (null != imageFileName && imageFileName.length() > 0) {

			if (imageFileName.indexOf(".") > 0) {
				try {
					return imageFileName.substring(imageFileName.indexOf(".") + 1,
							imageFileName.length()).toLowerCase();
				} catch (Exception ex) {
					return "";
				}
			} else {
				return "";
			}
		} else {
			return "";
		}
	}

	/**
	 * 获取图片宽高大小
	 * @param image
	 * @return
	 */
	protected HashMap<String, String> getImageWHS(File image) {
		HashMap<String, String> retMap = new HashMap<String, String>();

		FileInputStream fi = null;
		BufferedImage sourceImg = null;
		try {
			fi = new FileInputStream(image);
			sourceImg = javax.imageio.ImageIO.read(fi);

			retMap.put("width", sourceImg.getWidth() + "");
			retMap.put("height", sourceImg.getHeight() + "");
			retMap.put("size", image.length() + "");
		} catch (Exception e) {

			retMap = null;
			e.printStackTrace();
		} finally {
			try {
				sourceImg.flush();
				fi.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return retMap;
	}
	
	/**
	 * 判断文件上传时的错误类型。0，正常。1，上传不允许的类型错误。2，上传文件大小错误。3，其他错误。
	 * @return
	 */
	public int getFileFieldError(){
		if(getFieldErrors().isEmpty())
			return 0;
		Map<String,List<String>> mapx=this.getFieldErrors();
		try{
			for(String key : mapx.keySet()){
				if(mapx.get(key).get(0).indexOf("not allowed")>=0)
					return 1;
			}
		}catch(Exception e)
		{
			return 3;
		}
		return 2;
	}
	
	
	/**
	 * 从操作map中查询是否是限制操作
	 * 
	 * @param status
	 * @param methodName
	 * @return
	 */
	/*
	 * protected boolean isPermitOperation(Integer status, String methodName) {
	 * Map<OperationType, List<String>> operamap = OperationType.OPERAMAP;
	 * List<String> list = operamap.get(OperationType
	 * .getOperationTypeByStatus(status)); boolean flag =
	 * list.contains(methodName); if (flag) { if (status.intValue() ==
	 * OperationType.TYPE_DEATH.getStatus()) { throw new ServiceException(80); }
	 * else { throw new ServiceException(81, OperationType.PLAYSTATUS
	 * .get(OperationType.getOperationTypeByStatus(status))); } } return flag; }
	 */
}
